import { createContext, useContext, useState, useEffect, ReactNode } from 'react';

// 支持的区块链类型
export type SupportedChain = 'solana' | 'bsc' | 'xlayer';

// 钱包状态接口
export interface WalletState {
  connected: boolean;
  connecting: boolean;
  address: string | null;
  chain: SupportedChain | null;
  balance: string | null;
  // 记录当前选择的 EVM Provider（BSC / XLayer 使用）
  evmProvider?: EthereumWallet | null;
  evmProviderId?: string | null;
}

// 交易类型定义
export interface SolanaTransaction {
  serialize: () => Uint8Array;
}

export interface EVMTransaction {
  from: string;
  to: string;
  value?: string;
  data?: string;
  gas?: string;
  gasPrice?: string;
}

export type Transaction = SolanaTransaction | EVMTransaction;

// 钱包接口类型
interface SolanaWallet {
  connect: () => Promise<{ publicKey: { toString: () => string } }>;
  signTransaction: (transaction: SolanaTransaction) => Promise<SolanaTransaction>;
}

interface EthereumWallet {
  request: (params: { method: string; params?: unknown[] }) => Promise<unknown>;
  on: (event: string, handler: (...args: unknown[]) => void) => void;
  removeListener: (event: string, handler: (...args: unknown[]) => void) => void;
}

interface ExtendedWindow extends Window {
  solana?: SolanaWallet;
  phantom?: object;
  ethereum?: EthereumWallet;
  web3?: object;
}

// 钱包操作接口
export interface WalletActions {
  connectWallet: (chain: SupportedChain, specificProvider?: unknown, providerId?: string) => Promise<void>;
  disconnectWallet: () => Promise<void>;
  switchChain: (chain: SupportedChain) => Promise<void>;
  signTransaction: (transaction: Transaction) => Promise<string>;
  getBalance: () => Promise<string>;
}

// 多链钱包上下文
export interface MultiChainWalletContextType extends WalletState, WalletActions {
  isSupported: (chain: SupportedChain) => boolean;
}

const MultiChainWalletContext = createContext<MultiChainWalletContextType | null>(null);

// 检查是否安装了对应的钱包扩展
const checkWalletSupport = (chain: SupportedChain): boolean => {
  if (typeof window === 'undefined') return false;
  
  const extendedWindow = window as ExtendedWindow;
  
  switch (chain) {
    case 'solana':
      return !!extendedWindow.solana || !!extendedWindow.phantom;
    case 'bsc':
    case 'xlayer':
      return !!extendedWindow.ethereum || !!extendedWindow.web3;
    default:
      return false;
  }
};

// 获取钱包网络配置
const getNetworkConfig = (chain: SupportedChain) => {
  switch (chain) {
    case 'bsc':
      return {
        chainId: '97', // BSC Testnet
        chainName: 'BSC Testnet',
        rpcUrls: ['https://data-seed-prebsc-1-s1.binance.org:8545/'],
        nativeCurrency: {
          name: 'BNB',
          symbol: 'BNB',
          decimals: 18,
        },
        blockExplorerUrls: ['https://testnet.bscscan.com/'],
      };
    case 'xlayer':
      return {
        chainId: '0x7A0', // XLayer Testnet (1952)
        chainName: 'XLayer Testnet',
        rpcUrls: [process.env.NEXT_PUBLIC_XLAYER_RPC_URL!],
        nativeCurrency: {
          name: 'OKB',
          symbol: 'OKB',
          decimals: 18,
        },
        blockExplorerUrls: ['https://www.oklink.com/xlayer-test/'],
      };
    default:
      return null;
  }
};

export function MultiChainWalletProvider({ children }: { children: ReactNode }) {
  const [walletState, setWalletState] = useState<WalletState>({
    connected: false,
    connecting: false,
    address: null,
    chain: null,
    balance: null,
  });

  // 检查是否支持指定链
  const isSupported = (chain: SupportedChain): boolean => {
    return checkWalletSupport(chain);
  };

  // 连接钱包
  const connectWallet = async (chain: SupportedChain, specificProvider?: unknown, providerId?: string): Promise<void> => {
    if (!isSupported(chain)) {
      throw new Error(`${chain} wallet not supported or not installed`);
    }

    setWalletState(prev => ({ ...prev, connecting: true }));

    try {
      if (chain === 'solana') {
        await connectSolanaWallet();
      } else {
        await connectEVMWallet(chain, specificProvider, providerId);
      }
    } catch (error) {
      setWalletState(prev => ({ ...prev, connecting: false }));
      throw error;
    }
  };

  // 连接 Solana 钱包
  const connectSolanaWallet = async (): Promise<void> => {
    const { solana } = window as ExtendedWindow;
    if (!solana) {
      throw new Error('Solana wallet not found');
    }

    const response = await solana.connect();
    const address = response.publicKey.toString();
    
    setWalletState({
      connected: true,
      connecting: false,
      address,
      chain: 'solana',
      balance: null,
    });
  };

  // 连接 EVM 钱包 (BSC/XLayer)
  const connectEVMWallet = async (chain: SupportedChain, specificProvider?: unknown, providerId?: string): Promise<void> => {
    // 使用指定的 provider 或者默认的 window.ethereum
    const ethereum = (specificProvider as EthereumWallet) || (window as ExtendedWindow).ethereum;
    
    if (!ethereum) {
      throw new Error('Ethereum wallet not found');
    }
    
    console.log('使用钱包连接:', {
      chain,
      hasSpecificProvider: !!specificProvider,
      isMetaMask: (ethereum as { isMetaMask?: boolean }).isMetaMask,
      isOkxWallet: (ethereum as { isOkxWallet?: boolean }).isOkxWallet
    });
    
    const networkConfig = getNetworkConfig(chain);

    const ensureChain = async () => {
      if (!networkConfig) return;
      const targetChainId = networkConfig.chainId.toLowerCase();
      try {
        const currentChainId = (await ethereum.request({ method: 'eth_chainId' }) as string).toLowerCase();
        if (currentChainId === targetChainId) return; // 已在目标链
      } catch {
        // 忽略读取失败，继续尝试切换
      }
      try {
        await ethereum.request({
          method: 'wallet_switchEthereumChain',
          params: [{ chainId: networkConfig.chainId }],
        });
      } catch (switchError: unknown) {
        // 4902: 未添加链 -> 添加后再切换
        if (typeof switchError === 'object' && switchError && 'code' in switchError && (switchError as { code?: number }).code === 4902) {
          await ethereum.request({
            method: 'wallet_addEthereumChain',
            params: [networkConfig],
          });
          // 等待钱包内部状态更新
          await new Promise(r => setTimeout(r, 300));
          await ethereum.request({
            method: 'wallet_switchEthereumChain',
            params: [{ chainId: networkConfig.chainId }],
          });
        } else if (typeof switchError === 'object' && switchError && 'code' in switchError && (switchError as { code?: number }).code === 4001) {
          throw new Error('用户拒绝切换网络');
        } else if (typeof switchError === 'object' && switchError && 'message' in switchError && typeof (switchError as { message?: string }).message === 'string' && (switchError as { message: string }).message.includes('Provider is not connected')) {
          // 某些钱包在尚未完成初始连接时会抛出该错误，重试一次
            await new Promise(r => setTimeout(r, 500));
            await ethereum.request({
              method: 'wallet_switchEthereumChain',
              params: [{ chainId: networkConfig.chainId }],
            });
        } else {
          throw switchError;
        }
      }
    };

    let accounts: string[] = [];

    // 先尝试请求账户；如果 provider 报未连接，再先切链后重试请求账户
    try {
      accounts = await ethereum.request({ method: 'eth_requestAccounts' }) as string[];
    } catch (e: unknown) {
      if (typeof e === 'object' && e && 'message' in e && typeof (e as { message?: string }).message === 'string' && (e as { message: string }).message.includes('Provider is not connected')) {
        await ensureChain();
        accounts = await ethereum.request({ method: 'eth_requestAccounts' }) as string[];
      } else if (typeof e === 'object' && e && 'code' in e && (e as { code?: number }).code === 4001) {
        throw new Error('用户拒绝连接钱包');
      } else {
        throw e;
      }
    }

    if (!accounts.length) throw new Error('No accounts found');

    // 确保切换到目标链
    await ensureChain();

    const address = accounts[0];

    setWalletState({
      connected: true,
      connecting: false,
      address,
      chain,
      balance: null,
      evmProvider: ethereum,
      evmProviderId: providerId || (ethereum as unknown as { isMetaMask?: boolean })?.isMetaMask ? 'metamask' : providerId || 'unknown'
    });
  };

  // 断开钱包连接
  const disconnectWallet = async (): Promise<void> => {
    setWalletState({
      connected: false,
      connecting: false,
      address: null,
      chain: null,
      balance: null,
  evmProvider: null,
  evmProviderId: null,
    });
  };

  // 切换链
  const switchChain = async (chain: SupportedChain): Promise<void> => {
    if (walletState.chain === chain) return;
    
    await disconnectWallet();
    await connectWallet(chain);
  };

  // 签名交易
  const signTransaction = async (transaction: Transaction): Promise<string> => {
    if (!walletState.connected || !walletState.address) {
      throw new Error('Wallet not connected');
    }

    if (walletState.chain === 'solana') {
      const { solana } = window as ExtendedWindow;
      if (!solana) throw new Error('Solana wallet not found');
      const signed = await solana.signTransaction(transaction as SolanaTransaction);
      return signed.serialize().toString();
    } else {
  const ethereum = walletState.evmProvider || (window as ExtendedWindow).ethereum;
  if (!ethereum) throw new Error('Ethereum wallet not found');
  return await ethereum.request({
        method: 'eth_sendTransaction',
        params: [transaction],
      }) as string;
    }
  };

  // 获取余额
  const getBalance = async (): Promise<string> => {
    if (!walletState.connected || !walletState.address) {
      throw new Error('Wallet not connected');
    }

    if (walletState.chain === 'solana') {
      // Solana 余额获取逻辑
      return '0'; // 占位符
    } else {
  const ethereum = walletState.evmProvider || (window as ExtendedWindow).ethereum;
  if (!ethereum) throw new Error('Ethereum wallet not found');
  const balance = await ethereum.request({
        method: 'eth_getBalance',
        params: [walletState.address, 'latest'],
      }) as string;
      return (parseInt(balance, 16) / 1e18).toString();
    }
  };

  // 监听账户变化
  useEffect(() => {
    if (typeof window === 'undefined') return;

  const ethereum = walletState.evmProvider || (window as ExtendedWindow).ethereum;
    if (ethereum) {
      const handleAccountsChanged = (...args: unknown[]) => {
        const accounts = args[0] as string[];
        if (accounts.length === 0) {
          disconnectWallet();
        } else if (walletState.chain !== 'solana') {
          setWalletState(prev => ({
            ...prev,
            address: accounts[0],
          }));
        }
      };

      const handleChainChanged = () => {
        // 网络变化时重新连接
        if (walletState.connected && walletState.chain !== 'solana') {
          window.location.reload();
        }
      };

      try {
        ethereum.on('accountsChanged', handleAccountsChanged);
        ethereum.on('chainChanged', handleChainChanged);
      } catch (e) {
        console.warn('当前 provider 不支持事件监听', e);
      }

      return () => {
        try {
          ethereum.removeListener('accountsChanged', handleAccountsChanged);
          ethereum.removeListener('chainChanged', handleChainChanged);
        } catch {}
      };
    }
  }, [walletState.connected, walletState.chain, walletState.evmProvider]);

  const contextValue: MultiChainWalletContextType = {
    ...walletState,
    connectWallet,
    disconnectWallet,
    switchChain,
    signTransaction,
    getBalance,
    isSupported,
  };

  return (
    <MultiChainWalletContext.Provider value={contextValue}>
      {children}
    </MultiChainWalletContext.Provider>
  );
}

// Hook 使用多链钱包
export function useMultiChainWallet(): MultiChainWalletContextType {
  const context = useContext(MultiChainWalletContext);
  if (!context) {
    throw new Error('useMultiChainWallet must be used within MultiChainWalletProvider');
  }
  return context;
}
